/********************************************************************
	filename: 	Vector2D.cpp
	created:	2010/04/16
	author:		Xiuwei Chen

	purpose:	Implement of class Vector2D

	All rights Reserved
*********************************************************************/

#include "Vector2D.h"

/// <Summary>
/// Zero of Vector2D
/// </Summary>
const Vector2D Vector2D::Zero = Vector2D(0, 0);

/// <Summary>
/// default constructor
/// </Summary>
Vector2D::Vector2D(): x(0), y(0)
{
}

/// <Summary>
/// copy constructor
/// </Summary>
Vector2D::Vector2D(const Vector2D &v)
	: x(v.x), y(v.y)
{
}

/// <Summary>
/// constructor
/// </Summary>
Vector2D::Vector2D(double _x, double _y)
	: x(_x), y(_y)
{
}

/// <Summary>
/// set value
/// </Summary>
void Vector2D::SetValue(double _x, double _y)
{
	x = _x;
	y = _y;
}

/// <Summary>
/// overload operation: assignment
/// </Summary>
Vector2D & Vector2D::operator = (const Vector2D &v)
{
	x = v.x;
	y = v.y;
	return *this;
}

/// <Summary>
/// overload operation: "=="
/// </Summary>
bool Vector2D::operator == (const Vector2D &v) const
{
	return x == v.x && y == v.y;
}

/// <Summary>
/// overload operation: "!="
/// </Summary>
bool Vector2D::operator != (const Vector2D &v) const
{
	return x != v.x || y != v.y;
}

/// <Summary>
/// overload operation: "<"
/// </Summary>
bool Vector2D::operator < (const Vector2D &v) const
{
	if(x != v.x) return x < v.x;
	return y < v.y;
}

/// <Summary>
/// overload operation: unary "-"
/// </Summary>
Vector2D Vector2D::operator - () const
{
	return Vector2D(-x, -y);
}

/// <Summary>
/// overload operation: "+"
/// </Summary>
Vector2D Vector2D::operator + (const Vector2D &v) const
{
	return Vector2D(x + v.x, y + v.y);
}

/// <Summary>
/// overload operation: "-"
/// </Summary>
Vector2D Vector2D::operator - (const Vector2D &v) const
{
	return Vector2D(x - v.x, y - v.y);
}

/// <Summary>
/// overload operation: "*" for scalar
/// </Summary>
Vector2D Vector2D::operator * (double f) const
{
	return Vector2D(x * f, y * f);
}

/// <Summary>
/// overload operation: "/" for scalar
/// </Summary>
Vector2D Vector2D::operator / (double f) const
{
	return Vector2D(x / f, y / f);
}

/// <Summary>
/// overload operation: self-converse "+="
/// </Summary>
Vector2D & Vector2D::operator += (const Vector2D &v)
{
	x += v.x;
	y += v.y;
	return *this;
}

/// <Summary>
/// overload operation: self-converse "-="
/// </Summary>
Vector2D & Vector2D::operator -= (const Vector2D &v)
{
	x -= v.x;
	y -= v.y;
	return *this;
}

/// <Summary>
/// overload operation: self-converse "*="
/// </Summary>
Vector2D & Vector2D::operator *= (double f)
{
	x *= f;
	y *= f;
	return *this;
}

/// <Summary>
/// overload operation: self-converse "/="
/// </Summary>
Vector2D & Vector2D::operator /= (double f)
{
	x /= f;
	y /= f;
	return *this;
}

/// <Summary>
/// vector Normalize
/// </Summary>
void Vector2D::Normalize()
{
	double squa = x * x + y * y;
	if(squa > 0)
	{
		double d = 1.0 / sqrt(squa);
		x *= d;
		y *= d;
	}
}

/// <Summary>
/// overload operation: "*" for dot product
/// </Summary>
double Vector2D::operator * (const Vector2D &v) const
{
	return x * v.x + y * v.y;
}

/// <Summary>
/// get the module of vecotr
/// </Summary>
double Vector2D::Norm () const
{
	return sqrt(x * x + y * y);
}

/// <Summary>
/// get the module square of vector
/// </Summary>
double Vector2D::Norm2 () const
{
	return x * x + y * y;
}

/// <Summary>
/// get projection on 2D vector
/// </Summary>
Vector2D Vector2D::Projection(const Vector2D &v) const
{
	return v * ((*this * v) / v.Norm2());
}

/// <Summary>
/// get Perpendicular vector (clockwise direction)
/// </Summary>
Vector2D Vector2D::Vertical(bool unit) const
{
	Vector2D ret(y, -x);
	if(unit == true)
	{
		ret.Normalize();
	}
	return ret;
}

/// <Summary>
/// Translation by 2D vector
/// </Summary>
void Vector2D::Translation(const Vector2D &v)
{
	x += v.x;
	y += v.y;
}

/// <Summary>
/// rotate counter clockwise around the origin point (radian)
/// </Summary>
void Vector2D::Rotation(double angle)
{
	double _cos = cos(angle);
	double _sin = sin(angle);
	double _x = x * _cos - y * _sin;
	y = x * _sin+ y * _cos;
	x = _x;
}

/// <Summary>
/// rotate counter clockwise around a point (radian)
/// </Summary>
void Vector2D::Rotation(const Vector2D &p, double angle)
{
	double _cos = cos(angle);
	double _sin = sin(angle);
	double _x = p.x + (x - p.x) * _cos - (y - p.y) * _sin;
	y = p.y + (x - p.x) * _sin + (y - p.y) * _cos;
	x = _x;
}